﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace TUlingWpf.Heplers
{
    public static class PasswordBoxHelper
    { // 1. 定义可绑定的 Password 附加属性
        public static readonly DependencyProperty PasswordProperty =
            DependencyProperty.RegisterAttached(
                "Password",
                typeof(string),
                typeof(PasswordBoxHelper),
                new FrameworkPropertyMetadata(
                    string.Empty,
                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, // 支持双向绑定
                    OnPasswordPropertyChanged) // 属性值改变时的回调
            );

        // 2. 定义附加属性，用于管理 PasswordChanged 事件的订阅（避免内存泄漏）
        public static readonly DependencyProperty AttachProperty =
            DependencyProperty.RegisterAttached(
                "Attach",
                typeof(bool),
                typeof(PasswordBoxHelper),
                new PropertyMetadata(false, Attach)
            );

        private static readonly DependencyProperty IsUpdatingProperty =
            DependencyProperty.RegisterAttached("IsUpdating", typeof(bool), typeof(PasswordBoxHelper));

        // 附加属性的 Get/Set 方法
        public static void SetAttach(DependencyObject dp, bool value) => dp.SetValue(AttachProperty, value);

        public static bool GetAttach(DependencyObject dp) => (bool)dp.GetValue(AttachProperty);

        public static void SetPassword(DependencyObject dp, string value) => dp.SetValue(PasswordProperty, value);

        public static string GetPassword(DependencyObject dp) => (string)dp.GetValue(PasswordProperty);

        private static void SetIsUpdating(DependencyObject dp, bool value) => dp.SetValue(IsUpdatingProperty, value);

        private static bool GetIsUpdating(DependencyObject dp) => (bool)dp.GetValue(IsUpdatingProperty);

        // 3. 核心逻辑：处理 Attach 属性的变化，用于订阅或取消订阅事件
        private static void Attach(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is PasswordBox passwordBox))
                return;

            if ((bool)e.OldValue)
            {
                // 如果从 true 变为 false，则取消事件订阅
                passwordBox.PasswordChanged -= PasswordChanged;
            }

            if ((bool)e.NewValue)
            {
                // 如果从 false 变为 true，则订阅事件
                passwordBox.PasswordChanged += PasswordChanged;
            }
        }

        // 4. 当附加的 Password 属性值发生变化时（例如从 ViewModel 设置），更新 PasswordBox 的密码
        private static void OnPasswordPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is PasswordBox passwordBox))
                return;

            // 如果是由内部更新触发的，则不做处理，防止循环
            if (GetIsUpdating(passwordBox))
                return;

            // 临时取消事件监听，避免不必要的递归
            passwordBox.PasswordChanged -= PasswordChanged;
            // 更新 PasswordBox 的实际密码
            passwordBox.Password = e.NewValue?.ToString() ?? string.Empty;
            // 重新订阅事件
            passwordBox.PasswordChanged += PasswordChanged;
        }

        // 5. 当用户在 PasswordBox 中输入时，将新密码同步到附加属性
        private static void PasswordChanged(object sender, RoutedEventArgs e)
        {
            if (!(sender is PasswordBox passwordBox))
                return;

            // 设置更新标志，防止在 OnPasswordPropertyChanged 中再次触发更新
            SetIsUpdating(passwordBox, true);
            // 将 PasswordBox 中的密码值设置到我们定义的附加属性中
            SetPassword(passwordBox, passwordBox.Password);
            // 重置更新标志
            SetIsUpdating(passwordBox, false);
        }
    }
}